package com.yimils.core.sys.beanUtils;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yimils.core.sys.entity.ResourceEntity;
import com.yimils.core.sys.entity.RoleEntity;
import com.yimils.core.sys.entity.UserRoleEntity;
import com.yimils.core.sys.mapper.RoleMapper;
import com.yimils.core.sys.po.UserRoleDo;
import com.yimils.core.sys.service.ResourceService;
import com.yimils.core.sys.service.RoleService;
import com.yimils.core.sys.service.UserRoleService;
import com.yimils.core.sys.vo.UserRoleVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


@Component
public class RoleVoBeanUtils {

    @Resource(name = "userRoleService")
    private UserRoleService userRoleService;

    @Resource(name = "roleService")
    private RoleService roleService;

    @Resource(name = "resourceService")
    private ResourceService resourceService;


    public IPage<UserRoleVo> deepClone(IPage<UserRoleEntity> src) {
        IPage<UserRoleVo> pages = new Page<>();
        pages.setCurrent(src.getCurrent());
        pages.setSize(src.getSize());
        pages.setTotal(src.getTotal());
        pages.setPages(src.getPages());
        pages.setRecords(cloneRecords(src.getRecords()));
        return pages;
    }


    public List<UserRoleVo> cloneRecords(List<UserRoleEntity> src) {
        List<UserRoleVo> recordsVo = new ArrayList<>();
        for (UserRoleEntity entity : src) {

        }
        return recordsVo;
    }

    public Set<String> makePermissionsByUserId(Long userId) {
        List<RoleEntity> entities = getRolesByUserId(userId);
        if (entities == null || entities.size() <= 0) {
            return new TreeSet<>();
        }
        return makePermissions(entities);
    }

    public List<RoleEntity> getRolesByUserId(Long userId) {
        List<UserRoleDo> userRoleDos = userRoleService.getRolesByUserId(userId);
        return (List<RoleEntity>) roleService.listByIds(userRoleDos.stream().map(UserRoleDo::getRid)
                .collect(Collectors.toList()));
    }

    public Set<String> makePermissions(List<RoleEntity> roles) {
        if (isAdminByRoles(roles)) {
            return getAllPermissions();
        } else {
            return getPermissionsByRoleId(roles);
        }
    }

    private Set<String> getAllPermissions() {
        List<ResourceEntity> dirs = resourceService.getDirAll();
        return makeResourceSetByDirs(dirs, null);
    }

    public boolean isAdminByUserId(Long userId) {
        //List<UserRoleDo> userRoleDos = roleMapper.getRolesByUserId(userId);
        List<UserRoleDo> userRoleDos = userRoleService.getRolesByUserId(userId);
        for (UserRoleDo userRoleDo : userRoleDos) {
            return isAdminByRoleId(userRoleDo.getRid());
        }
        return false;
    }

    private boolean isAdminByRoleId(Long roleId) {
        if (roleId.equals(UserRoleDo.R_ADMIN)) {
            return true;
        }
        return false;
    }

    private boolean isAdminByRoles(List<RoleEntity> roles) {
        for (RoleEntity role : roles) {
            if (role.getId().equals(UserRoleDo.R_ADMIN)) {
                return true;
            }
        }
        return false;
    }

    private Set<String> getPermissionsByRoleId(List<RoleEntity> roles) {
        Set<String> resourceSet = new TreeSet<>();
        for (RoleEntity role : roles) {
            List<ResourceEntity> dirs = resourceService.getDirByRoleId(role.getId());
            resourceSet.addAll(makeResourceSetByDirs(dirs, role.getId()));
        }
        return resourceSet;
    }

    private Set<String> makeResourceSetByDirs(List<ResourceEntity> dirs, Long roleId) {
        Set<String> resourceSet = new TreeSet<>();
        for (ResourceEntity dir : dirs) {
            List<ResourceEntity> menus;
            if (roleId == null) {
                menus = resourceService.getMenuAll(dir.getId());
            } else {
                menus = resourceService.getMenuByRoleId(dir.getId(), roleId);
            }
            for (ResourceEntity menu : menus) {
                List<ResourceEntity> perms;
                if (roleId == null) {
                    perms = resourceService.getPermAll(menu.getId());
                } else {
                    perms = resourceService.getPermByRoleId(menu.getId(), roleId);
                }
                for (ResourceEntity perm : perms) {
                    resourceSet.add(dir.getName() + ":" + menu.getName() + ":" + perm.getOpt());
                }
            }
        }
        return resourceSet;
    }
}
